import gzip
import zlib
import http.cookiejar
from urllib.request import Request, urlopen, build_opener, install_opener, HTTPCookieProcessor
from urllib.error import URLError, HTTPError
from io import BytesIO

from weibosender.http_utils.http_method import HttpMethod


class HttpRequest:
    # HTTP_GET请求
    @staticmethod
    def get(url, headers=None, cookies=None):
        return HttpRequest.request(HttpMethod.GET, url, headers, cookies)

    # HTTP_POST请求
    @staticmethod
    def post(url, data, headers=None, cookies=None):
        return HttpRequest.request(HttpMethod.POST, url, headers, cookies, data)

    @staticmethod
    def request(method, url, headers=None, cookies=None, data=None):
        req = Request(url)
        # 设置Cookie
        if not cookies:
            cookies = http.cookiejar.CookieJar()
        cookie_processor = HTTPCookieProcessor(cookies)
        opener = build_opener(cookie_processor)
        # 设置头信息
        if headers:
            opener.addheaders = headers
        install_opener(opener)
        try:
            if method is HttpMethod.GET:
                return HttpRequest.handle_get(req)
            elif method is HttpMethod.POST:
                return HttpRequest.handle_post(req, data, cookies)
            else:
                return HttpRequest.handle_get(req)
        except HTTPError as e:
            print('The server couldn\'t fulfill the request.')
            print('Error code: ', e.code)
        except URLError as e:
            print('We failed to reach a server.')
            print('Reason: ', e.reason)
        return None

    @staticmethod
    def handle_get(req):
        with urlopen(req) as response:
            response_text = HttpRequest.read_response(response)
            response.close()
            return response_text

    @staticmethod
    def handle_post(req, data, cookies):
        with urlopen(req, data) as response:
            response_result = {
                'response_text': HttpRequest.read_response(response),
                'cookies': cookies
            }
            response.close()
        return response_result

    # 读取Http_Response
    @staticmethod
    def read_response(response):
        try:
            if response.info().get('Content-Encoding') == 'gzip':
                buf = BytesIO(response.read())
                return gzip.GzipFile(fileobj=buf).read().decode('utf8')

            elif response.info().get('Content-Encoding') == 'deflate':
                decompress = zlib.decompressobj(-zlib.MAX_WBITS)
                inflated = decompress.decompress(response.read())
                inflated += decompress.flush()
                return inflated.decode('utf8')
        except Exception as e:
            print(response.read())
            print(e)
            return None

        return response.read().decode('utf8')
